package com.reuters.rfa.example.omm.idn.tstrend;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Choice;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import com.reuters.rfa.example.framework.idn.RefChain;
import com.reuters.rfa.example.framework.idn.RefChainClient;
import com.reuters.rfa.example.framework.idn.RefChainTimeSeriesDefDb;
import com.reuters.rfa.example.framework.idn.TS1TimeSeries;
import com.reuters.rfa.example.framework.idn.TS1TimeSeriesClient;
import com.reuters.rfa.example.framework.sub.SubAppContext;
import com.reuters.rfa.example.framework.sub.SubAppContextClient;
import com.reuters.rfa.example.utility.gui.HistoryTextField;
import com.reuters.rfa.example.utility.gui.StatusBar;
import com.reuters.ts1.TS1Constants;
import com.reuters.ts1.TS1Fields;

/**
 * An interactive interface for user inputs, constructs TimeSeries instances,
 * and displays the results using a TSTrendCanvas object.
 */
public class TSTrendPanel extends Panel implements TS1TimeSeriesClient, ActionListener,
        SubAppContextClient, RefChainClient
{
    /**
	 * 
	 */
    private static final long serialVersionUID = 1L;

    // Constructor
    public TSTrendPanel(SubAppContext service)
    {
        _service = service;
        _service.setAutoDictionaryDownload();
        _service.setCompletionClient(this);
        setLayout(new BorderLayout());

        Panel northPanel = new Panel(new GridLayout(2, 1));
        Panel p1 = new Panel();
        p1.setLayout(new GridLayout(1, 3));
        Panel p1a = new Panel(new FlowLayout(FlowLayout.LEFT));
        p1a.add(new Label("Symbol:"));
        _symbolEdit = new HistoryTextField("TRI.N", 15, 15);
        p1a.add(_symbolEdit);
        _symbolEdit.setToolTipText("RIC to add to quote list");
        _symbolEdit.addActionListener(this);
        _symbolEdit.setEnabled(false); // wait for dictionary

        Panel p1b = new Panel(new FlowLayout(FlowLayout.LEFT));
        p1b.add(new Label("Period:"));
        _periodChoice = new Choice();
        _periodChoice.addItem("Daily");
        _periodChoice.addItem("Weekly");
        _periodChoice.addItem("Monthly");
        p1b.add(_periodChoice);

        p1.add(p1a);
        p1.add(p1b);

        final Panel p4a = new Panel(new FlowLayout(FlowLayout.LEFT));
        p4a.add(new Label("Number of Samples: "));
        _numSampleEdit = new TextField("30");
        p4a.add(_numSampleEdit);
        p4a.setVisible(true);
        p1.add(p4a);

        // ------------------------

        Panel submitPanel = new Panel();
        Button submitButton = new Button("Send Request");
        submitPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
        submitPanel.add(submitButton);
        Button resetButton = new Button("Reset");
        submitPanel.add(resetButton);

        northPanel.add(p1);
        northPanel.add(submitPanel);

        // ------------------------

        _canvas = new TSTrendCanvas();
        _statusBar = new StatusBar();
        add("North", northPanel);
        add("South", _statusBar);
        add("Center", _canvas);

        submitButton.addActionListener(this);
        resetButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                reset();
            }
        });
        setEnabled(false);
    }

    // Operations
    /**
     * Reset the GUI components to their default values.
     **/
    public void reset()
    {
        _symbolEdit.setText("");
        _periodChoice.select("Daily");
        _numSampleEdit.setText("30");
    }

    // Event Processing -- from ActionListener
    /**
     * Handle event generated by "Send Request" button
     **/
    public void actionPerformed(ActionEvent ae)
    {
        String ricName = _symbolEdit.getText();
        if (ricName == null)
        {
            _statusBar.setStatusFixed("A valid symbol name must be provided.");
        }

        int pindex = _periodChoice.getSelectedIndex();

        int numSamples = 0;
        try
        {
            numSamples = Integer.parseInt(_numSampleEdit.getText());
        }
        catch (NumberFormatException e)
        {
        }

        // if (Trace.debugEnabled())
        {
            System.out.print("TimeSeries: Requesting series for ");
            System.out.println("symbol " + ricName + ":");
            System.out.print("   Period: " + TS1Constants.periodString(pindex));
            System.out.print(", NumSamples: " + numSamples);
        }
        // All input values are checked, construct a series now.
        //
        getTimeSeries(ricName, pindex, numSamples);

    }

    public void processTimeSeriesComplete(TS1TimeSeries ser)
    {
        _statusBar.setStatusFixed("Series Status: Data received. Drawing...");
        TS1Fields series = new TS1Fields(ser.series(), ser.numberOfSamples(), _defDb.defDb());
        _canvas.update(series);
        _statusBar.setStatusFixed("Series Status: Series complete");
    }

    public void processTimeSeriesError(TS1TimeSeries ser)
    {
        TS1Fields series = new TS1Fields(ser.series(), ser.numberOfSamples(), _defDb.defDb());
        if (series.getSampleCount() > 0)
            _canvas.update(series);
        else
            _canvas.clearDisplay();
        _statusBar.setStatusFixed("Series Error:" + ser.text());
    }

    // Utility
    protected Date getDateFromText(String dateString)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        sdf.setCalendar(c);
        try
        {
            sdf.parse(dateString);
            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            c.set(Calendar.MILLISECOND, 0);
            return c.getTime();
        }
        catch (ParseException pe)
        {
            return null;
        }
    }

    protected void getTimeSeries(String ricName, int period, int numSamples)
    {
        _statusBar.setStatusFixed("Sending request");
        if (numSamples <= 0)
        {
            _statusBar.setStatusFixed("Invalid sample count given.");
            return;
        }

        _series = new TS1TimeSeries(_service, ricName, period, numSamples);
        _series.setClient(this);

        _canvas.clearDisplay();
        _canvas.clearTimeSeries();
        if (_series.isComplete())
            processTimeSeriesComplete(_series);
    }

    public void cleanup()
    {
        if (_defDb != null)
            _defDb.setClient(null);
        _statusBar.cleanUp();
        _service = null;
        _series = null;
    }

    public void refresh(Checkbox c, Panel p)
    {
        Container p3 = p.getParent();
        p.setVisible(true);
        for (int i = 0; i < 3; i++)
        {
            Component p3i = p3.getComponent(i);
            if (p3i == p)
                p3i.setVisible(true);
            else
                p3i.setVisible(false);
        }
        p3.validate();
        p3.repaint();
    }

    public void processComplete()
    {
        _defDb = new RefChainTimeSeriesDefDb(_service);
        _defDb.setClient(this);
        _statusBar.setStatusFixed("Service ready.  Waiting for TimeSeriesDefDb.");
    }

    public void processRefChainComplete(RefChain db)
    {
        db.setClient(null);
        setEnabled(true);
        _statusBar.setStatusFixed("TimeSeriesDefDb complete.");
        _symbolEdit.setEnabled(true); // wait for dictionary
    }

    public void processRefChainError(RefChain db, String text)
    {
        _statusBar.setStatusFixed(text);
    }

    // Data
    protected SubAppContext _service;
    protected TS1TimeSeries _series;
    protected HistoryTextField _symbolEdit;
    protected Choice _periodChoice;
    protected TextField _numSampleEdit;

    protected TSTrendCanvas _canvas;
    protected StatusBar _statusBar;

    RefChainTimeSeriesDefDb _defDb;

    protected CheckboxGroup _checkbox;
    protected Panel _selectPanel;
}
